package hsp.admin.app.base.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import hsp.admin.app.base.dto.PasswordDto;
import hsp.admin.app.base.mapper.UserMapper;
import hsp.admin.app.base.po.UserDetailPO;
import hsp.admin.app.base.po.UserPO;
import hsp.admin.app.base.po.UserRoleRelationPO;
import hsp.admin.app.base.service.IUserDetailService;
import hsp.admin.app.base.service.IUserRoleRelationService;
import hsp.admin.app.base.service.IUserService;
import hsp.admin.app.base.vo.UserVO;
import hsp.admin.app.base.info.UserInfo;
import hsp.admin.cache.ParamCache;
import hsp.admin.enums.ParamCode;
import hsp.admin.util.SessionUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.io.Serializable;

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, UserPO> implements IUserService {


    private final SessionUtil sessionUtil;

    private final UserMapper mapper;

    private final IUserDetailService userDetailService;

    private final IUserRoleRelationService userRoleRelationService;


    @Autowired
    public UserServiceImpl(
        SessionUtil sessionUtil,
        UserMapper mapper,
        IUserDetailService userDetailService,
        IUserRoleRelationService userRoleRelationService
    ){
        this.sessionUtil = sessionUtil;
        this.mapper = mapper;
        this.userDetailService = userDetailService;
        this.userRoleRelationService = userRoleRelationService;
    }

    @Override
    public UserPO getByUsername(String username){
        LambdaQueryWrapper<UserPO> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserPO::getUsername, username);
        return getOne(wrapper);
    }

    @Override
    public UserVO getVOById(long id) {
        UserPO po = getById(id);
        UserDetailPO userDetailPO = userDetailService.getById(id);
        UserVO vo = new UserVO();
        BeanUtils.copyProperties(po, vo);
        BeanUtils.copyProperties(userDetailPO, vo);
        return vo;
    }

    @Override
    public Page<UserVO> pageVO(Page<UserVO> page, UserVO vo) {
        return mapper.selectVOPage(page, vo);
    }


    @Override
    public boolean saveOrUpdate(UserVO vo) {
        UserPO po = new UserPO();
        UserDetailPO userDetailPO = new UserDetailPO();

        if(vo.getId() == null){
            UserPO exists = getByUsername(vo.getUsername());
            Assert.isNull(exists, "用户名已存在");

            po.setPassword(ParamCache.getValueByCode(ParamCode.RESET_PASSWORD));
        }
        BeanUtils.copyProperties(vo, po);
        BeanUtils.copyProperties(vo, userDetailPO);
        saveOrUpdate(po);

        userDetailPO.setUserId(po.getId());
        return userDetailService.saveOrUpdate(userDetailPO);
    }

    @Transactional
    @Override
    public boolean removeById(Serializable id) {
        super.removeById(id);
        userDetailService.removeById(id);

        LambdaQueryWrapper<UserRoleRelationPO> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserRoleRelationPO::getUserId, id);
        return userRoleRelationService.remove(wrapper);
    }

    @Override
    public void resetPassword(long id) {
        UserPO po = getById(id);
        po.setPassword(ParamCache.getValueByCode(ParamCode.RESET_PASSWORD));
        updateById(po);
    }

    @Override
    public void updatePassword(PasswordDto passwordDto) {
        UserPO po = getById(sessionUtil.getUserId());
        Assert.isTrue(StringUtils.equals(po.getPassword(), passwordDto.getOldPassword()), "旧密码错误");
        Assert.isTrue(!StringUtils.equals(po.getPassword(), passwordDto.getNewPassword()), "新密码不能与旧密码一致");
        Assert.isTrue(StringUtils.equals(passwordDto.getNewPassword(), passwordDto.getConfirmPassword()), "两次输入的密码不一致");
        po.setPassword(passwordDto.getConfirmPassword());
        updateById(po);
    }

    @Override
    public UserInfo fetchInfo() {
        UserVO vo = getVOById(sessionUtil.getUserId());
        UserInfo info = new UserInfo();
        BeanUtils.copyProperties(vo, info);
        return info;
    }

}
